#include "app_message.h"
#include "log/log.h"
#include <stdlib.h>
#include <string.h>
#include "cJSON/cJSON.h"
#include <stdio.h>
#include <ctype.h>
#include <assert.h>

// 得到十六进制字符对应的十进制值
int hex_to_int (char c)
{
    if (c>='0' && c<='9')
        return c - '0';
    else if (c>='A' && c<='F')
        return c - 'A' + 10;
    else if (c>='a' && c<='f')
        return c - 'a' + 10;
}


// 将十六进制字符串转换为二进制数组
// 实现将十六进制字符串转换为二进制数组的函数
static  char* hex_to_binary(const char *hex, int *binLength) {
   
    int hex_len = strlen(hex);
    int byte_len = hex_len / 2 + 1;
    char *binary = (char *)malloc(byte_len);

    int bin_index = 0;
    for(int i=0; i<hex_len; i+=2) 
    {
        binary[bin_index++] = hex_to_int(hex[i]) << 4 | hex_to_int(hex[i+1]);
        
    }
    // 最后一位放结束符
    binary[byte_len-1] = '\0';
  
    *binLength = byte_len - 1;

    return binary;
}

// 将二进制数组转换为十六进制字符串
static char *binary_to_hex(const unsigned char *binary_arr, int binary_len) {
    int hex_len = binary_len * 2 + 1;
    char *hex_str = (char *)malloc(hex_len);

    // 遍历二进制数组，将每个字节转换为两位十六进制字符
    for (int i = 0; i < binary_len; i++) {
        // binary_arr[i] => 二位的十六进制
        sprintf(&hex_str[i * 2], "%02X", binary_arr[i]);
    }
    // 写入结束符
    hex_str[hex_len - 1] = '\0';

    return hex_str;
}

/**
 * @brief 根据消息二进制数据初始化创建消息结构体
 */
Message *app_message_initByBinary(char *binary, int len)
{
    // 初始Message结构体：动态分配内存
    Message *message = (Message *)malloc(sizeof(Message));
    if (message == NULL)
    {
        log_error("malloc message failed");
        return NULL;
    }
    // 将message的内存所有位置置为0
    memset(message, 0, sizeof(Message));   

    // 初始化conn_type属性
    memcpy(&message->conn_type, binary, 1); // 要求前面部分的位必须是0
    // 初始化id_len
    memcpy(&message->id_len, binary+1, 1);
    // 初始化msg_len
    memcpy(&message->msg_len, binary+2, 1);
    // 检查len的合法性
    if (len != 3 + message->id_len + message->msg_len)
    {
        log_error("binary length is not correct");
        // 释放message
        free(message);
        return NULL;
    }

    // 初始化payload
    message->payload = malloc(message->id_len + message->msg_len);
    memcpy(message->payload, binary+3, message->id_len + message->msg_len);

    log_debug("initByBinary succes, conn_type: %d, id_len: %d, msg_len: %d, payload=%s", 
        message->conn_type, message->id_len, message->msg_len, message->payload);

    // 返回message
    return message;
}

/**
 * @brief 根据消息json数据初始化创建消息结构体
 */
Message *app_message_initByJson(char *json)
{
    // 解析json数据， 得到conn_type, id, msg
    cJSON *root = cJSON_Parse(json);
    if (root == NULL)
    {
        log_error("json parse failed");
        return NULL;
    }
    int conn_type = cJSON_GetObjectItem(root, "conn_type")->valueint;
    char *id_hex = cJSON_GetObjectItem(root, "id")->valuestring;
    char *msg_hex = cJSON_GetObjectItem(root, "msg")->valuestring;

    // 初始化Messsage结构体：动态分配内存
    Message *message = (Message *)malloc(sizeof(Message));
    if (message == NULL)
    {
        log_error("malloc message failed");
        cJSON_Delete(root); // 释放cJSON
        return NULL;
    }
    // 初始化内部属性
    message->conn_type = conn_type;
    
    // 得到二进制id, 同时指定message中的id_len
    char *id = hex_to_binary(id_hex, &message->id_len);
    char *msg = hex_to_binary(msg_hex, &message->msg_len);
    log_debug("id_hex=%s, id=%s, id_len=%d", id_hex,id, message->id_len);
    // 将id和msg合并到message的payload中
    message->payload = malloc(message->id_len + message->msg_len);
    memcpy(message->payload, id, message->id_len);
    memcpy(message->payload+message->id_len, msg, message->msg_len);

    // 释放cJSON
    cJSON_Delete(root);
    // free(id_hex);  // 不需要我们释放
    // free(msg_hex);
    free(id);
    free(msg);

    log_debug("initByJson succes, conn_type: %d, id_len: %d, msg_len: %d, payload=%s", 
        message->conn_type, message->id_len, message->msg_len, message->payload);

    // 返回message
    return message;
}

/**
 * @brief 将消息结构体转换为json数据
 */
int app_message_toJson(Message *message, char *json, int len)
{
    // 创建一个空的cJSON对象来存储conn_type, id, msg
    cJSON *root = cJSON_CreateObject();

    // 将message中的conn_type添加到root中
    cJSON_AddNumberToObject(root, "conn_type", message->conn_type);
    // 得到二进制id和msg
    char id[message->id_len];
    char msg[message->msg_len];
    memcpy(id, message->payload, message->id_len);
    memcpy(msg, message->payload+message->id_len, message->msg_len);
    // 得到十六进制id和msg
    char *id_hex = binary_to_hex(id, message->id_len);
    char *msg_hex = binary_to_hex(msg, message->msg_len);

    // 将id和msg添加到root中
    cJSON_AddStringToObject(root, "id", id_hex);
    cJSON_AddStringToObject(root, "msg", msg_hex);

    // 将root转换为json字符串, 并拷贝到json中
    char *json_str = cJSON_Print(root);
    // 判断json空间是否足够
    if (len < strlen(json_str) +1)
    {
        log_error("json length is not enough");
        cJSON_Delete(root);
        free(json_str);
        free(id_hex);
        free(msg_hex);

        return -1;
    }
    strcpy(json, json_str);

    // 释放资源
    free(id_hex);
    free(msg_hex);
    free(json_str);
    cJSON_Delete(root);

    return strlen(json);
}

/**
 * @brief 将消息结构体转换为二进制数据
 */
int app_message_toBinary(Message *message, char *binary, int len)
{
    // 检查binary的长度是否足够
    if (len < 3 + message->id_len + message->msg_len)
    {
        log_error("binary length is not enough");
        return -1;
    }


    // 将message中的各个属性数据拷贝到binary对应的位置
    memcpy(binary, &message->conn_type, 1);
    memcpy(binary+1, &message->id_len, 1);
    memcpy(binary+2, &message->msg_len, 1);
    memcpy(binary+3, message->payload, message->id_len + message->msg_len);

    return 3 + message->id_len + message->msg_len;
}


/**
 * @brief 释放消息
 */
void app_message_free(Message *message)
{
    if (message->payload)
    {
        free(message->payload);
    }
    free(message);
}